/*
 * $Id: time.h,v 1.33 2006-04-04 08:53:51 bacon Exp $
 */

#ifndef _XP_BAS_TIME_H_
#define _XP_BAS_TIME_H_

#include <xp/types.h>
#include <xp/macros.h>

#if defined(_WIN32)
	#include <time.h>

	#ifdef XP_WINSOCK_IN_ORDER
	#include <windows.h>
	#include <winsock2.h>
	#include <ws2tcpip.h>
	#else
	#include <winsock2.h>
	#include <ws2tcpip.h>
	#include <windows.h>
	#endif

	typedef struct timeval xp_timeval_t;
	typedef struct timezone xp_timezone_t;
	typedef struct timespec xp_timespec_t;
#elif defined(__linux)
	#include <time.h>
	#include <sys/time.h>

	#if 0
	struct xp_timeval_t
	{
		long tv_sec; /* seconds */
		long tv_usec; /* microseconds */
	};

	struct xp_timezone_t
	{
		int tz_minuteswest;
		int tz_dsttime;
	};

	struct xp_timespec_t
	{
		long tv_sec; /* seconds */
		long tv_nsec; /* nanoseconds */
	};

	typedef struct xp_timeval_t xp_timeval_t;
	typedef struct xp_timezone_t xp_timezone_t;
	typedef struct xp_timespec_t xp_timespec_t;
	#endif

	typedef struct timeval xp_timeval_t;
	typedef struct timezone xp_timezone_t;
	typedef struct timespec xp_timespec_t;
#else
	#include <time.h>
	#include <sys/time.h>

	typedef struct timeval xp_timeval_t;
	typedef struct timezone xp_timezone_t;
	typedef struct timespec xp_timespec_t;
#endif

/* number of milliseconds since the Epoch (00:00:00 UTC, Jan 1, 1970) */
typedef xp_long_t xp_time_t;

struct xp_utime_t
{
	short msec;   /* millisecond (0 - 999) */
	short sec;    /* seconds (0 - 59) */
	short min;    /* minutes (0 - 59) */
	short hour;   /* hours (0 - 23) */
	short day;    /* day of month (1 - 31) */
	short mon;    /* month of year (0 - 11) */
	short year;   /* year - XP_UTIME_BASE_YEAR */
	short wday;
	short yday;
};

typedef struct xp_utime_t xp_utime_t; 
typedef struct tm xp_tm_t;

#define XP_TIME_BASE_YEAR  (1900)
#define XP_UTIME_BASE_YEAR  XP_TIME_BASE_YEAR

#define XP_EPOCH_YEAR  ((xp_time_t)1970)
#define XP_EPOCH_MON   ((xp_time_t)1)
#define XP_EPOCH_DAY   ((xp_time_t)1)
#define XP_EPOCH_WDAY  ((xp_time_t)4)

#define XP_DAY_IN_WEEK  ((xp_time_t)7)
#define XP_MON_IN_YEAR  ((xp_time_t)12)
#define XP_HOUR_IN_DAY  ((xp_time_t)24)
#define XP_MIN_IN_HOUR  ((xp_time_t)60)
#define XP_MIN_IN_DAY   (XP_MIN_IN_HOUR * XP_HOUR_IN_DAY)
#define XP_SEC_IN_MIN   ((xp_time_t)60)
#define XP_SEC_IN_HOUR  (XP_SEC_IN_MIN * XP_MIN_IN_HOUR)
#define XP_SEC_IN_DAY   (XP_SEC_IN_MIN * XP_MIN_IN_DAY)
#define XP_MSEC_IN_SEC  ((xp_time_t)1000)
#define XP_MSEC_IN_MIN  (XP_MSEC_IN_SEC * XP_SEC_IN_MIN)
#define XP_MSEC_IN_HOUR (XP_MSEC_IN_SEC * XP_SEC_IN_HOUR)
#define XP_MSEC_IN_DAY  (XP_MSEC_IN_SEC * XP_SEC_IN_DAY)

#define XP_USEC_IN_MSEC ((xp_time_t)1000)
#define XP_NSEC_IN_USEC ((xp_time_t)1000)
#define XP_USEC_IN_SEC  ((xp_time_t)XP_USEC_IN_MSEC * XP_MSEC_IN_SEC)

#define XP_TIMEVAL_TO_TIME(tv) \
	((tv).tv_sec * XP_MSEC_IN_SEC + (tv).tv_usec / XP_USEC_IN_MSEC)

#define XP_TIMESPEC_TO_TIME(tv) \
	((tv).tv_sec * XP_MSEC_IN_SEC + (tv).tv_nsec / (XP_USEC_IN_MSEC * XP_NSEC_IN_USEC))

#define XP_TIME_TO_TIMEVAL(t,tv) { \
	(tv)->tv_sec = (t) / XP_MSEC_IN_SEC; \
	(tv)->tv_usec = ((t) % XP_MSEC_IN_SEC) * XP_USEC_IN_MSEC; \
}

#define XP_TIME_TO_TIMESPEC(t,tv) { \
	(tv)->tv_sec = (t) / XP_MSEC_IN_SEC; \
	(tv)->tv_nsec = ((t) % XP_MSEC_IN_SEC) * XP_USEC_IN_MSEC * XP_NSEC_IN_USEC; \
}

#ifdef __cplusplus
extern "C" {
#endif

/*
 * FUNCTION: xp_sleep
 */
void xp_sleep (xp_time_t interval);

/*
 * FUNCTION: xp_gettime
 */
int xp_gettime (xp_time_t* value);

/*
 * FUNCTION: xp_settime
 */
int xp_settime (xp_time_t value);

/*
 * FUNCTION: xp_time_to_utime
 */
int xp_time_to_utime (xp_time_t t, xp_utime_t* ut);

/*
 * FUNCTION: xp_utime_to_time
 */
int xp_utime_to_time (xp_utime_t* ut, xp_time_t* t);

int xp_gmtime (xp_time_t t, xp_tm_t* ct); 
int xp_localtime (xp_time_t t, xp_tm_t* ct); 
int xp_mktime (xp_tm_t* ct, xp_time_t* t);

xp_size_t xp_formattime (
	xp_char_t* buf, xp_size_t size, const xp_char_t* fmt, xp_tm_t* tm);

#ifdef __cplusplus
}
#endif

#endif
